﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PServiceBus.Core.Interface;
using PServiceBus.Core.Runtime;
using PServiceBus.Core.Runtime.Configuration;
using System.Diagnostics;

namespace PServiceBus.Core.Logger {
    /// <summary>
    /// Object factory class for using the current Logger for the bus
    /// </summary>
    public static class ESBLogger {
        static bool _enabled = false;
        static TraceSource _traceSource;
        static ESBLogger() {
            MethodHelper.Try(() =>
            {
                _enabled = ConfigurationProvider.LoggerConfig.Enabled;
                var logger = ServiceLocator<ILogger>.Get();
                if (logger == null) {
                    var esbLogger = ConfigurationProvider.ESBLogger;
                    if (esbLogger != null)
                        ServiceLocator<ILogger>.Set(Activator.CreateInstance(ConfigurationProvider.ESBLogger) as ILogger);
                    else ServiceLocator<ILogger>.Set(new EventLogLogger());
                }
                if (_enabled && !String.IsNullOrWhiteSpace(ConfigurationProvider.LoggerConfig.TracePath)) InitTrace();
            });
        }
        /// <summary>
        /// Create Tracing for logging information if tracing is enabled
        /// </summary>
        private static void InitTrace() {
            _traceSource = new TraceSource("PServiceBusTrace");
            var tr = new TextWriterTraceListener(ConfigurationProvider.LoggerConfig.TracePath);

            _traceSource.Switch = new SourceSwitch("PServiceBusSwitch", "PServiceBusSwitch");
            _traceSource.Switch.Level = SourceLevels.All; 
            tr.TraceOutputOptions = TraceOptions.DateTime | TraceOptions.Timestamp | TraceOptions.Callstack;

            _traceSource.Listeners.Clear();
            _traceSource.Listeners.Add(tr);
            Trace.AutoFlush = true;
        }
        private static void TraceMessage(TraceEventType traceType, string format, params object[] args) {
            if (_traceSource == null) return;
            _traceSource.TraceEvent(traceType, 0, format, args);
        }

        public static void TraceError(string format, params object[] args) {
            TraceMessage(TraceEventType.Error, format, args);
        }

        public static void TraceWarning(string format, params object[] args) {
            TraceMessage(TraceEventType.Warning, format, args);
        }

        public static void TraceInformation(string format, params object[] args) {
            TraceMessage(TraceEventType.Information, format, args);
        }

        public static void TraceCritical(string format, params object[] args) {
            TraceMessage(TraceEventType.Critical, format, args);
        }
        /// <summary>
        /// Log text using String.Format as passing args as the args to String.Format
        /// </summary>
        /// <param name="text"></param>
        /// <param name="args"></param>
        public static void Log(string text, params object[] args) {
            if (!_enabled) return;
            ServiceLocator<ILogger>.Get().Log(text, args);
        }
        public static void Log(Exception ex) {
            if (!_enabled) return;
            if (ex == null) return;
            ServiceLocator<ILogger>.Get().Log(ex);
        }
    }
}
